package com.hunan.chinamobile.app;


import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hunan.chinamobile.constant.SysConstant;
import com.hunan.chinamobile.core.BaseController;
import com.hunan.chinamobile.core.Result;
import com.hunan.chinamobile.core.ResultGenerator;
import com.hunan.chinamobile.dto.*;
import com.hunan.chinamobile.model.BaseStation;
import com.hunan.chinamobile.model.Device;
import com.hunan.chinamobile.model.DeviceData;
import com.hunan.chinamobile.model.Exceptions;
import com.hunan.chinamobile.onenet.OneNetBuilder;
import com.hunan.chinamobile.service.*;
import com.hunan.chinamobile.util.DateUtil;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController
@RequestMapping("/api")
public class APIController extends BaseController{

    @Resource
    private DeviceService deviceService;
    @Resource
    private DeviceDataService deviceDataService;
    @Resource
    private BaseStationService baseStationService;
    @Resource
    private ExceptionService exceptionService;
    @Resource
    private SysVersionService sysVersionService;

    /**
     * 登陆用户个人信息
     * @param request
     * @param response
     * @return
     */
    @GetMapping("/me")
    public Result requestLoginUser(HttpServletRequest request, HttpServletResponse response){
        UserDTO userDTO = getUser(request, response);
        userDTO.setPassword(null);
        return ResultGenerator.genSuccessResult(userDTO);
    }


    /**
     * APP首页接口
     * @param request
     * @param response
     * @return
     */
    @GetMapping("/index")
    public Result index(HttpServletRequest request, HttpServletResponse response){

        String cityId = getCityId(request, response);

        Map<String,Object> resultMap = new HashMap<>();

        int normalBaseStationNumber = 0;
        int errorBaseStationNumber = 0;
        int onlineDeviceNumber = 0;
        int offlineDeviceNumber = 0;
        int deviceTotal = 0;
        List<DeviceDTO> devices = deviceService.findList(cityId,null,null,null,null);

        if(devices != null && devices.size() > 0){
            deviceTotal = devices.size();
            Set<String> errorBaseStationSet = new HashSet<>();
            for(Device d : devices){
                int stat = d.getState();
                if(stat == 2) errorBaseStationSet.add(d.getBsId());

                if(d.getOnlineState()){
                    onlineDeviceNumber++;
                }else{
                    offlineDeviceNumber++;
                }
            }
            errorBaseStationNumber = errorBaseStationSet.size();
        }


        resultMap.put("errorBaseStationNumber",errorBaseStationNumber);
        resultMap.put("onlineDeviceNumber",onlineDeviceNumber);
        resultMap.put("offlineDeviceNumber",offlineDeviceNumber);
        resultMap.put("deviceTotal",deviceTotal);


        List<BaseStationDTO> bsList = new ArrayList<>();
        int baseStationTotal = 0;
        List<BaseStation> bss;
        if(!StringUtils.isEmpty(cityId)){
            bss = baseStationService.findByCityId(cityId);
        }else{
            bss = baseStationService.findAll();
        }
        if(bss != null && bss.size() > 0){
            baseStationTotal = bss.size();
            normalBaseStationNumber = baseStationTotal - errorBaseStationNumber;
            for(BaseStation bs : bss){
                BaseStationDTO bsDTO = new BaseStationDTO();
                bsDTO.setId(bs.getId());
                bsDTO.setBaseName(bs.getBaseName());
                bsDTO.setCreatedAt(bs.getCreatedAt());
                bsDTO.setUpdatedAt(bs.getUpdatedAt());
                bsDTO.setAddress(bs.getAddress());
                bsDTO.setCityId(bs.getCityId());
                bsDTO.setLinkman(bs.getLinkman());
                bsDTO.setLinkphone(bs.getLinkphone());
                bsDTO.setLat(bs.getLat());
                bsDTO.setLng(bs.getLng());
                bsDTO.setExceptionDTOList(exceptionService.findList(bs.getCityId(),bs.getId(),null,0));
                bsList.add(bsDTO);
            }
        }
        resultMap.put("normalBaseStationNumber",normalBaseStationNumber);
        resultMap.put("baseStationTotal",baseStationTotal);
        resultMap.put("baseStationList",bsList);

        List<ExceptionDTO> eDTO = exceptionService.findList(cityId,null,null,null);
        // 报警次数
        int errorCount = 0;
        // 光纤信号报警次数
        int fiberOpticErrorCount = 0;
        // 电压信号报警次数
        int voltageErrorCount = 0;
        // 已确认次数
        int affirmCount = 0;
        // 未确认次数
        int noAffirmCount = 0;
        // 已恢复次数
        int recoverCount = 0;
        // 未恢复次数
        int noRecoverCount = 0;

        if(eDTO != null && eDTO.size() > 0){
            for(ExceptionDTO e : eDTO){
                errorCount++;
                if(e.getType() == 1)
                    voltageErrorCount++;
                else if(e.getType() == 2)
                    fiberOpticErrorCount++;
                if(e.getAffirmState() == null || !e.getAffirmState())
                    noAffirmCount++;
                else
                    affirmCount++;
                if(e.getState() == null ||  !e.getState())
                    noRecoverCount++;
                else
                    recoverCount++;
            }
        }

        resultMap.put("errorCount",errorCount);
        resultMap.put("fiberOpticErrorCount",fiberOpticErrorCount);
        resultMap.put("voltageErrorCount",voltageErrorCount);
        resultMap.put("affirmCount",affirmCount);
        resultMap.put("noAffirmCount",noAffirmCount);
        resultMap.put("recoverCount",recoverCount);
        resultMap.put("noRecoverCount",noRecoverCount);

        return ResultGenerator.genSuccessResult(resultMap);
    }


    /**
     * 基站总览接口
     * @param request
     * @param response
     * @param bsName 基站名称，支持模糊搜索
     * @param ok  基站状态，0-全部，1-正常，2-报警
     * @param page 页码
     * @param size
     * @return
     */
    @GetMapping("/baseStation")
    public Result requestBaseStation(HttpServletRequest request, HttpServletResponse response,
                                     @RequestParam(required = false) String bsName,
                                     @RequestParam(required = false) Integer ok,
                                     @RequestParam(name = "page", defaultValue = "1") Integer page,
                                     @RequestParam(name = "size", defaultValue = "5") Integer size){
        String cityId = getCityId(request, response);

        Boolean okFlag = null;
        if(ok != null){
            if(ok == 1){
                okFlag = true;
            }else if(ok == 2){
                okFlag = false;
            }
        }

        PageHelper.startPage(page,size);
        List<BaseStationInfoDTO> bsDTOS = baseStationService.findByException(cityId,bsName, okFlag);

        PageInfo<BaseStationInfoDTO> pageInfo = new PageInfo<>(bsDTOS);

        bsDTOS.forEach(b->{
            BaseStationDTO bs = baseStationService.findDTOById(b.getId());
            b.setBsName(bs.getBaseName());
            b.setBsLocation(bs.getAddress());
            b.setCityName(bs.getCityName());
            b.setLinkMan(bs.getLinkman());
            b.setLinkPhone(bs.getLinkphone());
            b.setCreatedAt(bs.getCreatedAt());
        });

        return ResultGenerator.genSuccessResult(pageInfo);
    }

    /**
     * 定制版 WEB 基站详情接口
     * @param request
     * @param response
     * @param bsId 基站主键ID
     * @return
     */
    @GetMapping("/bs_info")
    public Result requestWEB_BS(HttpServletRequest request, HttpServletResponse response,
                                @RequestParam(required = false) String bsId){
        if(StringUtils.isEmpty(bsId)){
            return ResultGenerator.genFailResult("bsId参数为空！");
        }
        String cityId = getCityId(request, response);
        List<DeviceDTO> deviceDTOS = deviceService.findList(cityId,bsId,null,null,null);
        if(deviceDTOS.size() > 0){
            loadVoltageAndFiberOptic(deviceDTOS);
        }
        BaseStationDTO bsDTO = baseStationService.findDTOById(bsId);
        bsDTO.setExceptionDTOList(exceptionService.findList(bsDTO.getCityId(),bsDTO.getId(),null,0));

        Map<String,Object> resMap = new HashMap<>();
        resMap.put("baseStation",bsDTO);
        resMap.put("deviceList",deviceDTOS);
        return ResultGenerator.genSuccessResult(resMap);
    }


    /**
     * 基站详情接口
     * @param bsId 基站ID
     * @param page 页码
     * @param size
     * @return
     */
    @GetMapping("/baseStation_info")
    public Result requestBaseStationInfo(HttpServletRequest request, HttpServletResponse response,
                                         @RequestParam(required = false) String bsId,
                                         @RequestParam(name = "page", defaultValue = "1") Integer page,
                                         @RequestParam(name = "size", defaultValue = "5") Integer size){

        if(StringUtils.isEmpty(bsId)){
            return ResultGenerator.genFailResult("bsId参数为空！");
        }
        String cityId = getCityId(request, response);
        PageHelper.startPage(page,size);
        List<DeviceDTO> deviceDTOS = deviceService.findList(cityId,bsId,null,null,null);
        PageInfo<DeviceDTO> pageInfo = new PageInfo<>(deviceDTOS);
        if(deviceDTOS.size() > 0){
            loadVoltageAndFiberOptic(deviceDTOS);
        }
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    /**
     * 设备列表
     * @param deviceName 设备名称，支持模糊搜索
     * @param online 0-全部，1-在线，2-离线
     * @param page
     * @param size
     * @return
     */
    @GetMapping("/devices")
    public Result requestDevice(HttpServletRequest request, HttpServletResponse response,
                                @RequestParam(required = false) String deviceName,
                                @RequestParam(required = false) Integer online,
                                @RequestParam(name = "page", defaultValue = "1") Integer page,
                                @RequestParam(name = "size", defaultValue = "5") Integer size){

        String cityId = getCityId(request, response);

        if(online == null){
            return ResultGenerator.genFailResult("online参数为空！");
        }
        Integer ol = null;
        if(online == 1){
            ol = 1;
        }else if(online == 2){
            ol = 0;
        }
        PageHelper.startPage(page,size);
        List<DeviceDTO> deviceDTOS = deviceService.findList(cityId,null,deviceName,ol,null);
        PageInfo<DeviceDTO> pageInfo = new PageInfo<>(deviceDTOS);
        if(deviceDTOS.size() > 0){
            loadVoltageAndFiberOptic(deviceDTOS);
        }
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    private void loadVoltageAndFiberOptic(List<DeviceDTO> deviceDTOS){
        deviceDTOS.forEach(this::loadVoltageAndFiberOptic);
    }

    private void loadVoltageAndFiberOptic(DeviceDTO d){
        List<DeviceData> dds = deviceDataService.findByDeviceId(d.getDeviceId());
        if(dds != null && dds.size() > 0){
            d.setUpdatedAt(dds.get(0).getCreatedAt());
            for(DeviceData dd : dds){
                int t = dd.getType();
                double v = dd.getValue();
                switch (t){
                    case 1:
                        if(v==1){
                            d.setVoltageStatu(1);
                        }else if(v == 0){
                            d.setVoltageStatu(2);
                        }
                        break;
                    case 2:
                        if(v==1){
                            d.setFiberOpticStatu(1);
                        }else if(v == 0){
                            d.setFiberOpticStatu(2);
                        }
                        break;
                    case 3:
                        d.setVoltageVal(dd.getValue());
                        break;
                    case 4:
                        String rssi = SysConstant.getRssi((int)dd.getValue().doubleValue());
                        d.setRssi(rssi);
                        break;
                    default:
                        break;
                }
            }
        }else{
            d.setUpdatedAt(null);
        }
    }


    /**
     * 事件列表
     * @param request
     * @param response
     * @param type 事件类型，0-全部，1-电压，2-光纤
     * @param page
     * @param size
     * @return
     */
    @GetMapping("/exception")
    public Result requestException(HttpServletRequest request, HttpServletResponse response,
                                   @RequestParam(required = false) Integer type,
                                   @RequestParam(name = "page", defaultValue = "1") Integer page,
                                   @RequestParam(name = "size", defaultValue = "5") Integer size){

        String cityId = getCityId(request, response);

        if(type != null){
            if(type != 1 && type != 2){
                type = null;
            }
        }
        PageHelper.startPage(page,size);
        List<ExceptionDTO> exceptionDTOS = exceptionService.findList(cityId,null,type,null);
        PageInfo<ExceptionDTO> pageInfo = new PageInfo<>(exceptionDTOS);

        return ResultGenerator.genSuccessResult(pageInfo);
    }


    /**
     * 事件确认
     * @param request
     * @param response
     * @param exceptionId
     * @param userName
     * @return
     */
    @GetMapping("/dispose")
    public Result disposeException(HttpServletRequest request, HttpServletResponse response,
                                   @RequestParam(required = false) String exceptionId,
                                   @RequestParam(required = false) String userName){
        if(StringUtils.isEmpty(exceptionId)){
            return ResultGenerator.genFailResult("exceptionId参数为空！");
        }
        if(StringUtils.isEmpty(userName)){
            UserDTO userDTO = getUser(request, response);
            if(userDTO == null)return ResultGenerator.genFailResult("请登录后操作");
            userName = userDTO.getRealName();
        }
        Exceptions e = exceptionService.findById(exceptionId);
        if(e == null) return ResultGenerator.genFailResult("exceptionId不存在");

        e.setAffirmState(true);
        e.setAffirmUser(userName);
        e.setAffirmAt(new Date());

        exceptionService.update(e);
        return ResultGenerator.genSuccessResult();
    }

    @GetMapping("/device_info")
    public Result requestDeviceDetail(@RequestParam(required = false) String deviceId){
        if(StringUtils.isEmpty(deviceId)){
            return ResultGenerator.genFailResult("deviceId参数为空！");
        }
        DeviceDTO deviceDTO = deviceService.findDTO(deviceId);
        if(deviceDTO == null){
            return ResultGenerator.genFailResult("该设备不存在！");
        }
        loadVoltageAndFiberOptic(deviceDTO);

        List<DeviceData> dds = deviceDataService.findVoltageCurve(deviceDTO.getDeviceId(), DateUtil.getDayStart(),DateUtil.getDayEnd());

        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("info",deviceDTO);
        resultMap.put("curve",dds);

        return ResultGenerator.genSuccessResult(resultMap);
    }

    @GetMapping("/version")
    public Result requestVersion(){
        return ResultGenerator.genSuccessResult(sysVersionService.find());
    }

    @GetMapping("/count")
    public Result index2(HttpServletRequest request, HttpServletResponse response){
        UserDTO userDTO = getUser(request, response);
        String cityId = null;
        if(userDTO != null && !StringUtils.isEmpty(userDTO.getCityId()))
            cityId = userDTO.getCityId();
        int onlineDeviceNumber = 0;
        int offlineDeviceNumber = 0;
        int deviceTotal = 0;
        List<BaseStation> baseStationList = StringUtils.isEmpty(cityId) ? baseStationService.findAll():baseStationService.findByCityId(cityId);
        List<DeviceDTO> devices = deviceService.findList(cityId,null,null,null,null);
        Set<String> bsSet = new HashSet<>();
        if(devices != null && devices.size() > 0){
            deviceTotal = devices.size();
            for(DeviceDTO d : devices){
                if(d.getOnlineState()) onlineDeviceNumber++;
                else offlineDeviceNumber++;
                bsSet.add(d.getBsId());
            }
        }
        int yearCount = exceptionService.countByCurrYear(cityId);
        ExceptionCount ec = exceptionService.countByCurrMonth(cityId);
        if(ec == null) ec = new ExceptionCount();
        ExceptionCount uc = exceptionService.countByUntreated(cityId);
        if(uc == null) uc = new ExceptionCount();
        Map<String,Object> resMap = new HashMap<>();
        resMap.put("yearTotalCount",yearCount);
        resMap.put("monthTotalCount",ec.getTotalCount());
        resMap.put("monthVoltageTotalCount",ec.getVoltageTotalCount());
        resMap.put("monthFiberOpticTotalCount",ec.getFiberOpticTotalCount());
        resMap.put("voltageUntreatedCount",uc.getVoltageUntreatedCount());
        resMap.put("fiberOpticUntreatedCount",uc.getFiberOpticUntreatedCount());
        resMap.put("baseStationTotal",baseStationList != null ? baseStationList.size() : 0);
        resMap.put("deviceTotal",deviceTotal);
        resMap.put("onlineTotal",onlineDeviceNumber);
        resMap.put("offlineTotal",offlineDeviceNumber);
        List<ExceptionDTO> exceptionDTOS = exceptionService.findList(cityId,null,null,0);
        List<String> strList = new ArrayList<>();
        if(exceptionDTOS != null && exceptionDTOS.size() > 0){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            exceptionDTOS.forEach(x->{
                strList.add(sdf.format(x.getHappenAt())+" "+x.getDeviceName()+x.getExceptionDesc());
            });
        }
        resMap.put("exceptionList",strList);
        return ResultGenerator.genSuccessResult(resMap);
    }
}
